package com.xl.rentkeeper.business;

import android.text.TextUtils;

import com.squareup.wire.Message;
import com.xl.fuse.protos.account.Session;
import com.xl.fuse.protos.packet.Packet;
import com.xl.rentkeeper.App;
import com.xl.rentkeeper.common.SecurityCode;
import com.xl.rentkeeper.log.QLog;
import com.xl.rentkeeper.util.Aes;
import com.xl.rentkeeper.util.HexUtil;

import java.io.IOException;
import java.security.SecureRandom;

/**
 * Created by zhangjimin on 15/5/13.
 */
public class SecurityLogic extends BaseLogic{

    private static SecurityLogic sIns;
    public static SecurityLogic getInstance() {
        if (sIns == null) {
            synchronized (SecurityLogic.class) {
                if (sIns == null) {
                    sIns = new SecurityLogic();
                }
            }
        }
        return  sIns;
    }
    private static final String Key_Session = "key_session";

    Session session  = null;
    private SecurityLogic() {
        loadSessionInfo();
    }

    public Session getSession() {
        return session;
    }

    public synchronized void saveSessionInfo(Session session) {
        this.session = session;
        if (session != null) {
            byte[] data = session.toByteArray();
            saveBytesEncrypt(Key_Session, data);
        } else {
            removeKey(Key_Session);
        }
    }

    public synchronized void loadSessionInfo() {
        byte[] data = loadBytesEncrypt(Key_Session);
        if (data != null) {
            try {
                session = App.getWire().parseFrom(data,Session.class);
            } catch (IOException e) {
                e.printStackTrace();
                session = null;
            }
        }
        QLog.d(this, "load session info " + session);
    }

    public byte[] getRandomKey(int size) {
        SecureRandom random = new SecureRandom();
        byte[] iv = new byte[size];
        random.nextBytes(iv);
        return iv;
    }

    public void saveBytes(String name, byte[] key) {
        app.getSp().edit().putString(name, HexUtil.bytesToHex(key)).commit();
    }

    public byte[] loadBytes(String name) {
        String key = app.getSp().getString(name, null);
        if (key != null) {
            byte[] k = HexUtil.hexStringToByteArray(key);
            return k;
        }
        return null;
    }

    public boolean saveBytesEncrypt(String name, byte[] data) {
        try {
            byte[] enc = Aes.encrypt(data, SecurityCode.sDefaultKey, SecurityCode.sDefaultIv);
            saveBytes(name,enc);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public byte[] loadBytesEncrypt(String name) {
        byte[] enc = loadBytes(name);
        if (enc != null) {
            try {
                byte[] origin = Aes.decrypt(enc,SecurityCode.sDefaultKey,SecurityCode.sDefaultIv );
                return origin;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public void removeKey(String key) {
        if (TextUtils.isEmpty(key))
            return;
        app.getSp().edit().remove(key).commit();
    }


    public byte[] encodeDataUseSessionKey(byte[] data) throws Exception{
        byte[] ebody = new byte[0];
        if (data == null) {
            return ebody;
        }
        if (session == null) { // should never happen
            throw new RuntimeException("session null");
        } else {
            ebody = Aes.encrypt(data,session.key.toByteArray(),session.iv.toByteArray());
        }
        return ebody;
    }




    public byte[] encodeBody(long uin,String cmd,Message msg) throws Exception{
        byte[] ebody = new byte[0];
        if (msg == null) {
            return ebody;
        }
        byte[] body = msg.toByteArray();
        if (CMD_USER_LOGIN.equals(cmd) || uin == 0) {
            ebody = Aes.encrypt(body,SecurityCode.sDefaultKey,SecurityCode.sDefaultIv);
        } else {
            if (session == null) { // should never happen
                throw new RuntimeException("session null");
            } else {
                ebody = Aes.encrypt(body,session.key.toByteArray(),session.iv.toByteArray());
            }
        }
        return ebody;
    }

    public byte[] decodeEBody(Packet packet) throws Exception{
        if (packet == null || packet.eBody == null)
            return null;
        byte[] ebody = packet.eBody.toByteArray();
        byte[] body = null;
        if (CMD_USER_LOGIN.equals(packet.cmd)) {
            body = Aes.decrypt(ebody, SecurityCode.sDefaultKey, SecurityCode.sDefaultIv);
        } else {
            if (session == null) { // should never happen
                throw new RuntimeException("session null");
            } else {
                body = Aes.decrypt(ebody, session.key.toByteArray(), session.iv.toByteArray());
            }
        }
        return body;
    }
}
